import React from 'react';
import { SketchPicker } from 'react-color';
import {
  Input,
  Slider,
  Layout,
  Form,
  InputNumber,
  Button,
  Select,
  notification,
} from 'antd';
import { SettingOutlined } from '@ant-design/icons';
import html2canvas from 'html2canvas';
import _ from 'lodash';

import styles from './index.less';

export default class Component extends React.PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      content: '默认样式',
      color: '#000000',
      opacity: 50,
      fontSize: 16,
      fontWeight: 500,
      rotate: 315,
      bgColor: '#ffffff',
      bgOpacity: 0,
      width: 200,
      height: 200,
      // Base64 编码图片
      dataUrl: '',
      // 是否展示水印
      showShuiyin: false,
      // 是否展示配置项（<768px）
      showConfig: false,
    };
  }

  componentDidMount = () => {
    this.hanldeCreatePicture();
    console.log('v1.0.2');
  };

  /**
   * @description 16进制颜色转rgba
   * @param {*} color
   * @param {*} opacity
   * @returns
   */
  colorRgba = (color, opacity = 1) => {
    const toDecimal = (str, type = 1) => {
      const reg =
        type === 1 ? /([0-9a-fA-F])/g : type === 2 ? /([0-9a-fA-F]{2})/g : /./;
      const strArr = _.map(str.match(reg), (val) => {
        return type === 1
          ? _.parseInt(val + val, 16)
          : type === 2
          ? _.parseInt(val, 16)
          : 0;
      });
      return `rgba(${strArr.join(',')},${opacity})`;
    };

    // #fff
    if (color && /^#[0-9a-fA-F]{3}$/.test(color)) {
      return toDecimal(color, 1);
    }
    // #ffffff
    else if (color && /^#[0-9a-fA-F]{6}$/.test(color)) {
      return toDecimal(color, 2);
    }
    return '';
  };

  /**
   * @description event 表单值发生更改
   * @param {*} changedValues
   * @param {*} allValues
   */
  hanldeFormValuesChange = (changedValues, allValues) => {
    this.setState(
      {
        ...allValues,
      },
      () => {
        this.hanldeCreatePicture();
      },
    );
  };

  /**
   * @description 生成 Base64 编码图片
   */
  hanldeCreatePicture = async () => {
    let canvas = await html2canvas(this.refs.html2canvas, {
      backgroundColor: this.colorRgba(
        this.state.bgColor,
        this.state.bgOpacity / 100,
      ),
    });

    const dataUrl = canvas?.toDataURL('image/png');
    this.setState({
      dataUrl,
    });
  };

  /**
   * @description 下载水印图片
   */
  handleDownload = () => {
    const blob = this.dataUrl2Blob(this.state.dataUrl);
    const url = URL.createObjectURL(blob);
    const filename = 'shuiyin.png';

    this.pcDownload(url, filename);
    this.codeNotification();
  };

  pcDownload = (url, filename) => {
    const alink = document.createElement('a');
    const event = document.createEvent('HTMLEvents');
    event.initEvent('click', true, true);
    alink.download = filename;
    alink.href = url;

    alink.dispatchEvent(
      new MouseEvent('click', {
        bubbles: true,
        cancelable: true,
        view: window,
      }),
    );
    URL.revokeObjectURL(url);
  };

  /**
   * @description Base64 转 Blob
   * @param {*} dataUrl
   */
  dataUrl2Blob = (dataUrl) => {
    let byteString = atob(dataUrl.split(',')[1]);
    let mimeString = dataUrl.split(',')[0].split(':')[1].split(';')[0];
    let ab = new ArrayBuffer(byteString.length);
    let dw = new DataView(ab);
    for (let i = 0; i < byteString.length; i++) {
      dw.setUint8(i, byteString.charCodeAt(i));
    }
    return new Blob([ab], {
      type: mimeString,
    });
  };

  /**
   * @description 提示样式代码
   */
  codeNotification = () => {
    const args = {
      message: 'CSS 样式代码',
      description: (
        <pre>
          position: absolute; <br />
          top: 0; <br />
          left: 0; <br />
          width: 100%; <br />
          height: 100%; <br />
          background-repeat: repeat; <br />
          // 请修改路径 <br />
          bgckground-image: url(./shuiyin.png); <br />
          // 这行很重要 <br />
          pointer-events: none; <br />
        </pre>
      ),
      duration: 0,
    };
    notification.open(args);
  };

  renderLayoutContent = () => {
    return (
      <>
        <h2>水印图片效果展示</h2>
        <section className={styles.leftContent}>
          <div className={styles.boxContainer}>
            <div
              ref="html2canvas"
              style={{
                height: this.state.height,
                width: this.state.width,
                fontSize: this.state.fontSize,
                fontWeight: this.state.fontWeight,
                backgroundColor: this.colorRgba(
                  this.state.bgColor,
                  this.state.bgOpacity / 100,
                ),
              }}
              className={styles.box}
            >
              <p
                style={{
                  margin: 0,
                  transform: `rotate(${this.state.rotate}deg)`,
                  color: this.colorRgba(
                    this.state.color,
                    this.state.opacity / 100,
                  ),
                }}
              >
                {this.state.content}
              </p>
            </div>
          </div>
        </section>
      </>
    );
  };

  renderLayoutSider = () => {
    const initialValues = {
      content: this.state.content,
      color: this.state.color,
      opacity: this.state.opacity,
      fontSize: this.state.fontSize,
      fontWeight: this.state.fontWeight,
      rotate: this.state.rotate,
      // bgColor: this.state.bgColor,
      bgOpacity: this.state.bgOpacity,
      width: this.state.width,
      height: this.state.height,
    };

    const fontWeightSelect = (
      <Select>
        {_.map([100, 200, 300, 400, 500, 600, 700, 800, 900], (item) => {
          return (
            <Select.Option value={item} key={item}>
              {item}
            </Select.Option>
          );
        })}
      </Select>
    );

    return (
      <div style={{ height: '100%', position: 'relative' }}>
        <Button
          type="primary"
          className="setting-btn"
          onClick={() => this.setState({ showConfig: !this.state.showConfig })}
        >
          <SettingOutlined />
        </Button>
        <h2>配置项</h2>
        <div className={styles.rightContent}>
          <section className={styles.formContainer}>
            <Form
              labelCol={{ span: 8 }}
              wrapperCol={{ span: 14 }}
              layout="vertical"
              initialValues={initialValues}
              onValuesChange={this.hanldeFormValuesChange}
            >
              <Form.Item name="content" label="水印文字">
                <Input />
              </Form.Item>
              <Form.Item name="color" label="文字颜色">
                <Input type="color" />
              </Form.Item>
              <Form.Item name="opacity" label="文字颜色透明度">
                <Slider />
              </Form.Item>
              <Form.Item name="fontSize" label="文字字体大小">
                <Slider />
              </Form.Item>
              <Form.Item name="fontWeight" label="文字字体粗细">
                {fontWeightSelect}
              </Form.Item>
              <Form.Item name="rotate" label="文字旋转角度">
                <Slider max={360} />
              </Form.Item>
              {/* <Form.Item name="bgColor" label="背景颜色"> */}
              {/* 使用 react-color */}
              <Form.Item label="背景颜色">
                <SketchPicker
                  presetColors={['#1890ff', '#25b864', '#ff6f00']}
                  color={this.state.bgColor}
                  onChange={({ hex }) => {
                    this.setState(
                      {
                        bgColor: hex,
                      },
                      () => {
                        this.hanldeCreatePicture();
                      },
                    );
                  }}
                />
              </Form.Item>
              <Form.Item name="bgOpacity" label="背景颜色透明度">
                <Slider />
              </Form.Item>
              <Form.Item name="width" label="生成图片宽度">
                <InputNumber />
              </Form.Item>
              <Form.Item name="height" label="生成图片高度">
                <InputNumber />
              </Form.Item>
            </Form>
          </section>
          <section className={styles.btnContainer}>
            <Button
              type={this.state.showShuiyin ? '' : 'primary'}
              onClick={() =>
                this.setState({ showShuiyin: !this.state.showShuiyin })
              }
            >
              {this.state.showShuiyin ? '隐藏水印' : '展示水印'}
            </Button>
            <Button type="primary" onClick={this.handleDownload}>
              生成图片
            </Button>
          </section>
        </div>
      </div>
    );
  };

  render = () => {
    return (
      <div className={styles.createImage}>
        <Layout>
          <Layout.Content>{this.renderLayoutContent()}</Layout.Content>
          <Layout.Sider
            className={[styles.sider, this.state.showConfig && 'show-config']}
          >
            {this.renderLayoutSider()}
          </Layout.Sider>
        </Layout>
        {this.state.showShuiyin && (
          <div
            className={styles.shuiyin}
            style={{ backgroundImage: `url(${this.state.dataUrl})` }}
          />
        )}
      </div>
    );
  };
}
